<!--html模版部分-->
<template>
  <!-- 添加初始加载指示器 -->
  <div id="initialLoader" v-if="initialLoading" class="initial-loading-overlay">
    <div class="spinner-container">
      <div class="spinner-wrapper">
        <div class="spinner-circle"></div>
        <div class="spinner-dot"></div>
      </div>
      <p class="mt-3 text-primary">初始化中...</p>
    </div>
  </div>

  <div class="container-scroller">
    <div class="container-fluid page-body-wrapper full-page-wrapper">
      <div class="content-wrapper d-flex align-items-center auth px-0">
        <div class="row w-100 mx-0">
          <div class="col-lg-4 mx-auto">
            <div class="auth-form-light text-left py-5 px-4 px-sm-5">
              <div class="brand-logo">
                <img src="../../assets/images/logo.svg" alt="logo">
              </div>
              <h4>你好!让我们开始吧</h4>
              <h6 class="fw-light">登录继续</h6>
              <form class="pt-3">
                <div class="form-group">
<!--                  <h1>测试用户信息</h1>
                  <p>编号：{{ cs.number }}</p>
                  <p>密码：{{ cs.cipher }}</p>
                  <p>姓名：{{ cs.name }}</p>
                  <p>年龄：{{ cs.age }}</p>
                  <p>身份证号：{{ cs.id_number }}</p>
                  <p>激活状态：{{ cs.activate }}</p>
                  <p>余额：{{ cs.balance }}</p>
                  <p>工作状态：{{ cs.job }}</p>
                  <p>电话：{{ cs.phone }}</p>-->
                  <div>
  <input type="text" class="form-control form-control-lg" id="phoneInput" placeholder="手机号码" v-model="phoneNumber" @input="validatePhoneNumber" @keyup.enter="focusPasswordInput">
  <small v-if="!isPhoneValid" class="text-muted" style="font-size: 0.8rem; color: #999;">请输入有效的手机号码</small>
</div>
                </div>
                <div class="form-group">
                  <div class="input-group" style="position: relative;">
                    <input type="password" class="form-control form-control-lg" id="passwordInput" placeholder="密码" v-model="passwordInput" style="background-color: transparent;">
                    <div class="input-group-append" style="position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; z-index: 3; cursor: pointer;">
                      <span style="cursor: pointer; display: block; position: relative;" @click="togglePasswordVisibility">
                        <i v-if="passwordVisible" class="mdi mdi-eye-off" style="color: #000;"></i>
                        <i v-else class="mdi mdi-eye" style="color: #000;"></i>
                      </span>
                    </div>
                  </div>
                </div>
                <div class="mt-3">
                  <a class="btn btn-block btn-primary btn-lg font-weight-medium auth-form-btn" v-on:click="handleClick">登录</a>
                </div>
                <div class="my-2 d-flex justify-content-between align-items-center">
                  <div class="form-check">
                    <label class="form-check-label text-muted">
                      <input type="checkbox" class="form-check-input">
                      保持登录状态
                    </label>
                  </div>
                  <a href="#" class="auth-link text-black">忘记了密码?</a>
                </div>
                <div class="mb-2">
                  <button type="button" class="btn btn-block btn-facebook auth-form-btn">
                    <i class="ti-facebook me-2"></i>待定
                  </button>
                </div>
                <div class="text-center mt-4 fw-light">
                  没有账户？ <a href="" class="text-primary">注册</a>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 登录结果模态框 -->
  <div class="modal fade custom-modal" id="loginResultModal" tabindex="-1" role="dialog" aria-labelledby="loginResultModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
      <div class="modal-content">
        <div class="modal-header border-0" :class="loginSuccess ? 'bg-success' : 'bg-warning'">
          <h5 class="modal-title text-white" id="loginResultModalLabel">
            <i :class="loginSuccess ? 'mdi mdi-check-circle' : 'mdi mdi-alert-circle'" class="mr-2"></i>
            {{ loginSuccess ? '登录成功' : '登录失败' }}
          </h5>
          <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body py-5">
          <div class="text-center">
            <div class="icon-container mb-4" :class="loginSuccess ? 'success-icon' : 'error-icon'">
              <i :class="loginSuccess ? 'mdi mdi-check-circle-outline' : 'mdi mdi-close-circle-outline'"></i>
            </div>
            <h4 class="result-heading mb-3">{{ loginSuccess ? '欢迎回来！' : '登录失败' }}</h4>
            <p class="text-muted">{{ loginResultMessage }}</p>
            
            <div v-if="loginSuccess" class="progress-container mt-4">
              <div class="progress" style="height: 6px;">
                <div class="progress-bar bg-theme" role="progressbar" :style="{ width: redirectProgress + '%' }" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
              </div>
              
              <p class="mt-2 redirect-text">
                <small class="text-muted">{{ Math.ceil(redirectCountdown) }}秒后自动跳转到首页...</small>
              </p>
            </div>
          </div>
        </div>
        <div class="modal-footer border-0 d-flex justify-content-center">
          <button v-if="!loginSuccess" type="button" class="btn btn-light" data-bs-dismiss="modal">关闭</button>
          <button v-if="!loginSuccess" type="button" class="btn btn-theme" @click="retryLogin">
            <i class="mdi mdi-reload me-1"></i>重试
          </button>
          <button v-if="loginSuccess" type="button" class="btn btn-theme" @click="goToHome">
            立即前往
            <i class="mdi mdi-arrow-right ms-1"></i>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<!--定义组件：逻辑、方法、数据等-->
<script>

  import axios from "axios";
  import qs from 'qs';

  // 直接导入必要的脚本文件
  // import '@/assets/vendors/js/vendor-bundle-base.js';
  // import '@/assets/vendors/bootstrap-datepicker/bootstrap-datepicker.min.js';
  // import '@/utils/js/off-canvas.js';
  // import '@/utils/js/hoverable-collapse.js';
  // import '@/utils/js/template.js';
  // import '@/utils/js/settings.js';
  // import '@/utils/js/todolist.js';

  export default {
    name:"Login",
    data() {
      return {
        phoneNumber:'',
        passwordInput:'',
        cs:{},// 初始化为空对象
        isPhoneValid: true,
        isPasswordFocused: false,
        passwordVisible: false,
        // 登录结果相关
        loginSuccess: false,
        loginResultMessage: '',
        redirectCountdown: 3,
        redirectProgress: 0,
        redirectTimer: null,
        // 添加初始加载状态
        initialLoading: true,
        // 添加脚本加载状态追踪
        scriptsLoaded: false,
        // 脚本路径
        scriptPaths: {
          base: [
            '/src/assets/vendors/js/vendor-bundle-base.js',
            '/src/assets/vendors/bootstrap-datepicker/bootstrap-datepicker.min.js'
          ],
          utils: [
            '/src/utils/js/off-canvas.js',
            '/src/utils/js/hoverable-collapse.js',
            '/src/utils/js/template.js',
            '/src/utils/js/settings.js',
            '/src/utils/js/todolist.js'
          ]
        }
      }
    },
    created() {
      // 创建时立即显示加载状态
      this.initialLoading = true;
    },
    mounted(){
      // 显示初始加载状态
      this.initialLoading = true;

      // 确保页面DOM元素已经加载完成
      this.$nextTick(() => {
        const passwordInput = document.getElementById('passwordInput');
        if (passwordInput) {
          passwordInput.addEventListener('focus', () => {
            this.isPasswordFocused = true;
          });
          passwordInput.addEventListener('blur', () => {
            this.isPasswordFocused = false;
          });
        }
  
        // 检查脚本是否已通过其他方式加载
        if (typeof $ !== 'undefined' || typeof bootstrap !== 'undefined') {
          console.log('检测到外部已加载的脚本库，跳过重复加载');
          this.scriptsLoaded = true;
          this.initializeUI();
        } else {
          // 使用动态脚本加载
          this.loadAllScripts();
        }
      });
    },
    //验证账号密码
    methods: {
      // 加载所有必要脚本
      loadAllScripts() {
        console.log('开始加载所有必要脚本...');
        
        // 首先加载基础库
        this.loadScriptsSequentially(this.scriptPaths.base)
          .then(() => {
            console.log('基础UI库加载完成');
            // 然后加载工具脚本
            return this.loadScriptsSequentially(this.scriptPaths.utils);
          })
          .then(() => {
            console.log('UI工具脚本加载完成');
            this.scriptsLoaded = true;
            this.initializeUI();
          })
          .catch(err => {
            console.error('脚本加载失败:', err);
            // 尝试使用CDN作为备用
            this.loadBootstrapFallback();
          });
      },
      
      // 按顺序加载多个脚本
      async loadScriptsSequentially(urls) {
        for (const url of urls) {
          try {
            await this.loadScript(url);
            console.log(`${url} 加载成功`);
          } catch (e) {
            console.error(`${url} 加载失败`, e);
            throw e; // 重新抛出异常以便外部处理
          }
        }
      },
      
      // 加载单个脚本
      loadScript(src) {
        return new Promise((resolve, reject) => {
          // 检查脚本是否已经加载
          const existingScript = document.querySelector(`script[src*="${src.split('/').pop()}"]`);
          if (existingScript) {
            console.log(`脚本 ${src} 已存在，跳过加载`);
            resolve();
            return;
          }
          
          // 构建完整URL (处理相对路径和绝对路径)
          const fullSrc = src.startsWith('http') ? src : window.location.origin + src;
          
          // 创建新的脚本元素
          const script = document.createElement('script');
          script.src = fullSrc;
          script.async = false; // 保持脚本执行顺序
          
          script.onload = () => {
            console.log('脚本加载成功:', src);
            resolve();
          };
          
          script.onerror = (e) => {
            console.error('脚本加载失败:', src, e);
            reject(e);
          };
          
          document.head.appendChild(script);
        });
      },
      
      // 初始化UI组件
      initializeUI() {
        console.log('开始UI初始化');
        
        // 延时确保脚本加载完毕并初始化
        setTimeout(() => {
          // 初始化模态框
          this.initializeModals();
          
          // 所有脚本加载完成后，隐藏初始加载状态
          this.initialLoading = false;
          console.log('所有UI组件初始化完成，隐藏加载状态');
        }, 800);
      },
      
      // 初始化模态框
      initializeModals() {
        // 确保DOM已完全加载
        try {
          const modalElement = document.getElementById('loginResultModal');
          if (modalElement) {
            if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
              // 使用Bootstrap 5的方式初始化
              new bootstrap.Modal(modalElement);
              console.log('模态框初始化成功 (Bootstrap 5)');
            } else if (typeof $ !== 'undefined' && $.fn.modal) {
              // 降级为jQuery方式初始化
              $('#loginResultModal').modal({
                backdrop: 'static',
                keyboard: false,
                show: false
              });
              console.log('模态框初始化成功 (jQuery)');
            } else {
              console.warn('无法初始化模态框：缺少必要的库，尝试动态加载');
              this.loadBootstrapFallback();
            }
          } else {
            console.warn('模态框元素不存在');
          }
        } catch (err) {
          console.error('模态框初始化失败:', err);
          this.loadBootstrapFallback();
        }
      },
      
      // 如果Bootstrap未加载，尝试添加CDN版本作为备用
      loadBootstrapFallback() {
        if (typeof bootstrap === 'undefined') {
          console.log('正在加载Bootstrap备用CDN版本');
          
          // 添加Bootstrap 5 CDN
          const bootstrapCSS = document.createElement('link');
          bootstrapCSS.rel = 'stylesheet';
          bootstrapCSS.href = 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css';
          document.head.appendChild(bootstrapCSS);
          
          const bootstrapJS = document.createElement('script');
          bootstrapJS.src = 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js';
          bootstrapJS.onload = () => {
            console.log('Bootstrap CDN加载成功，重新初始化模态框');
            setTimeout(() => {
              this.initializeModals();
              this.initialLoading = false;
            }, 300);
          };
          bootstrapJS.onerror = (e) => {
            console.error('Bootstrap CDN加载失败', e);
            // 最终失败时也要取消加载状态
            this.initialLoading = false;
            alert('加载UI库失败，部分功能可能不可用。请刷新页面重试。');
          };
          document.head.appendChild(bootstrapJS);
        } else {
          // 确保即使失败也隐藏加载状态
          this.initialLoading = false;
        }
      },
      
      handleClick(){
        const data = {
          phone:this.phoneNumber,
          cipher:this.passwordInput,
        };
        const queryString = qs.stringify(data);

        // 开始加载动画
        this.showLoading(true);

        axios({
          method: "POST",
          url: "http://localhost:9001/user/login",
          data: queryString,
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          }
        }).then(res => {
          this.showLoading(false);
          
          if (res.data && res.data.number) {
            // 登录成功，将用户信息保存到localStorage
            localStorage.setItem('userInfo', JSON.stringify(res.data));
            
            // 显示成功弹窗
            this.showLoginResult(true, `欢迎回来，${res.data.name || '用户'}！`);
          } else {
            // 显示失败弹窗
            this.showLoginResult(false, '手机号或密码错误，请重新输入');
          }
        }).catch(error => {
          this.showLoading(false);
          console.error('登录失败：', error);
          
          // 显示错误信息
          this.showLoginResult(false, '网络错误，请检查您的网络连接后重试');
        });
      },
      
      /**
       * 显示登录结果模态框
       * @param {boolean} success 是否登录成功
       * @param {string} message 提示消息
       */
      showLoginResult(success, message) {
        this.loginSuccess = success;
        this.loginResultMessage = message;
        
        // 尝试使用Bootstrap 5的方式显示模态框
        const modalElement = document.getElementById('loginResultModal');
        
        try {
          if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
            const modal = bootstrap.Modal.getInstance(modalElement) || new bootstrap.Modal(modalElement);
            modal.show();
          } else if (typeof $ !== 'undefined' && $.fn.modal) {
            // 降级为jQuery方式显示
            $('#loginResultModal').modal('show');
          } else {
            // 最终降级：使用alert
            if (success) {
              alert('登录成功：' + message);
              this.$router.push('/index');
            } else {
              alert('登录失败：' + message);
            }
            return;
          }
          
          // 如果登录成功，开始倒计时和进度条
          if (success) {
            this.startRedirectCountdown();
          }
        } catch (error) {
          console.error('显示模态框失败:', error);
          // 降级处理
          if (success) {
            alert('登录成功：' + message);
            this.$router.push('/index');
          } else {
            alert('登录失败：' + message);
          }
        }
      },
      
      /**
       * 开始重定向倒计时
       */
      startRedirectCountdown() {
        this.redirectCountdown = 3;
        this.redirectProgress = 0;
        
        // 清除可能存在的旧计时器
        if (this.redirectTimer) {
          clearInterval(this.redirectTimer);
        }
        
        // 设置倒计时和进度条更新
        this.redirectTimer = setInterval(() => {
          this.redirectCountdown -= 0.1;
          // 显示时移除小数点，只显示整数部分
          this.redirectCountdown = parseFloat(this.redirectCountdown.toFixed(1));
          this.redirectProgress = (3 - this.redirectCountdown) / 3 * 100;
          
          if (this.redirectCountdown <= 0) {
            clearInterval(this.redirectTimer);
            this.goToHome();
          }
        }, 100);
      },
      
      /**
       * 导航到首页
       */
      goToHome() {
        // 清除计时器
        if (this.redirectTimer) {
          clearInterval(this.redirectTimer);
        }
        
        // 关闭模态框
        try {
          const modalElement = document.getElementById('loginResultModal');
          if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
            const modal = bootstrap.Modal.getInstance(modalElement);
            if (modal) modal.hide();
          } else if (typeof $ !== 'undefined' && $.fn.modal) {
            $('#loginResultModal').modal('hide');
          }
        } catch (err) {
          console.warn('关闭模态框时出错:', err);
        }
        
        // 延迟导航以确保模态框有时间关闭
        setTimeout(() => {
          this.$router.push('/index');
        }, 300);
      },
      
      /**
       * 重试登录
       */
      retryLogin() {
        // 关闭模态框
        try {
          const modalElement = document.getElementById('loginResultModal');
          if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
            const modal = bootstrap.Modal.getInstance(modalElement);
            if (modal) modal.hide();
          } else if (typeof $ !== 'undefined' && $.fn.modal) {
            $('#loginResultModal').modal('hide');
          }
        } catch (err) {
          console.warn('关闭模态框时出错:', err);
        }
        
        // 清空密码字段
        this.passwordInput = '';
        
        // 聚焦到密码字段
        setTimeout(() => {
          document.getElementById('passwordInput').focus();
        }, 300);
      },
      
      /**
       * 显示或隐藏加载动画
       * @param {boolean} show 是否显示加载动画
       */
      showLoading(show) {
        // 创建或获取现有的加载动画元素
        let loader = document.getElementById('loader-overlay');
        
        if (show) {
          if (!loader) {
            loader = document.createElement('div');
            loader.id = 'loader-overlay';
            loader.innerHTML = `
              <div class="spinner-container">
                <div class="spinner-wrapper">
                  <div class="spinner-circle"></div>
                  <div class="spinner-dot"></div>
                </div>
                <p class="mt-3 text-primary">登录中...</p>
              </div>
            `;
            document.body.appendChild(loader);
          }
          loader.style.display = 'flex';
        } else if (loader) {
          loader.style.display = 'none';
        }
      },
      
      validatePhoneNumber() {
        // 去除所有非数字字符
        this.phoneNumber = this.phoneNumber.replace(/[^0-9]/g, '');
        // 去除所有空格
        this.phoneNumber = this.phoneNumber.replace(/\s+/g, '');
        // 限制最大长度为11位
        if (this.phoneNumber.length > 11) {
          this.phoneNumber = this.phoneNumber.slice(0, 11);
        }
        // 验证手机号码格式
        const phoneRegex = /^1[3-9]\d{9}$/;
        this.isPhoneValid = phoneRegex.test(this.phoneNumber);
      },
      
      togglePasswordVisibility() {
        this.passwordVisible = !this.passwordVisible;
        const passwordInput = document.getElementById('passwordInput');
        if (passwordInput) {
          passwordInput.type = this.passwordVisible ? 'text' : 'password';
        }
      },
      
      /**
       * 聚焦到密码输入框
       */
      focusPasswordInput() {
        const passwordInput = document.getElementById('passwordInput');
        if (passwordInput) {
          passwordInput.focus();
        }
      }
    }
  }
</script>

<!--定义组件：CSS样式-->

<style>
  @import '@/assets/vendors/feather/feather.css';
  @import '@/assets/vendors/mdi/css/materialdesignicons.min.css';
  @import '@/assets/vendors/ti-icons/css/themify-icons.css';
  @import '@/assets/vendors/typicons/typicons.css';
  @import '@/assets/vendors/simple-line-icons/css/simple-line-icons.css';
  @import '@/assets/vendors/css/vendor-bundle-base.css';
  @import '@/utils/css/vertical-layout-light/style.css';
  
  /* 登录结果模态框样式 */
  .custom-modal .modal-content {
    border: none;
    border-radius: 12px;
    box-shadow: 0 15px 35px rgba(50, 50, 93, 0.1), 0 5px 15px rgba(0, 0, 0, 0.07);
    overflow: hidden;
  }
  
  .custom-modal .modal-header {
    padding: 1.5rem;
    position: relative;
  }
  
  /* 系统主题颜色变量 */
  :root {
    --theme-primary: #4B49AC;
    --theme-primary-light: #5E5CCA;
    --theme-primary-dark: #3D3C8A;
    --theme-success: #57B657;
    --theme-warning: #FFC100;
  }
  
  /* 成功状态背景 */
  .bg-success {
    background-color: var(--theme-success);
  }
  
  /* 警告状态背景 */
  .bg-warning {
    background-color: var(--theme-warning);
  }
  
  /* 主题颜色背景 */
  .bg-theme {
    background-color: var(--theme-primary);
  }
  
  /* 主题按钮 */
  .btn-theme {
    background-color: var(--theme-primary);
    border: none;
    color: white;
    transition: all 0.3s ease;
  }
  
  .btn-theme:hover {
    background-color: var(--theme-primary-dark);
    box-shadow: 0 5px 15px rgba(75, 73, 172, 0.3);
    transform: translateY(-2px);
  }
  
  .custom-modal .icon-container {
    width: 90px;
    height: 90px;
    margin: 0 auto;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s ease;
    transform: scale(0.5);
    animation: scaleIn 0.5s ease forwards;
  }
  
  .custom-modal .success-icon {
    background-color: rgba(87, 182, 87, 0.1);
    color: var(--theme-success);
  }
  
  .custom-modal .error-icon {
    background-color: rgba(255, 193, 0, 0.1);
    color: var(--theme-warning);
  }
  
  .custom-modal .icon-container i {
    font-size: 3.5rem;
  }
  
  .custom-modal .result-heading {
    transform: translateY(20px);
    opacity: 0;
    animation: fadeInUp 0.5s ease 0.2s forwards;
  }
  
  .custom-modal .text-muted {
    transform: translateY(20px);
    opacity: 0;
    animation: fadeInUp 0.5s ease 0.3s forwards;
  }
  
  .custom-modal .progress-container {
    transform: translateY(20px);
    opacity: 0;
    animation: fadeInUp 0.5s ease 0.4s forwards;
  }
  
  .custom-modal .modal-footer {
    padding: 1.2rem;
  }
  
  .custom-modal .modal-footer button {
    border-radius: 50px;
    padding: 0.5rem 1.5rem;
    font-weight: 500;
    transition: all 0.3s ease;
  }
  
  .custom-modal .progress {
    height: 6px;
    overflow: hidden;
    background-color: rgba(75, 73, 172, 0.1);
    border-radius: 8px;
  }
  
  .custom-modal .progress-bar {
    transition: width 0.1s linear;
  }
  
  /* 动画效果 */
  @keyframes scaleIn {
    0% { transform: scale(0.5); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
  }
  
  @keyframes fadeInUp {
    0% { transform: translateY(20px); opacity: 0; }
    100% { transform: translateY(0); opacity: 1; }
  }
  
  @keyframes progressPulse {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
  }
  
  .modal.fade .modal-dialog {
    transition: transform 0.3s ease-out, opacity 0.3s ease-out;
    transform: translate(0, -30px) scale(0.95);
    opacity: 0;
  }
  
  .modal.show .modal-dialog {
    transform: translate(0, 0) scale(1);
    opacity: 1;
  }
  
  .btn-close-white {
    filter: brightness(0) invert(1);
  }
  
  .me-1 {
    margin-right: 0.25rem;
  }
  
  .ms-1 {
    margin-left: 0.25rem;
  }
  
  /* 加载动画样式 */
  #loader-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(255, 255, 255, 0.9);
    z-index: 9999;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: all 0.3s ease;
    backdrop-filter: blur(3px);
  }
  
  .spinner-container {
    background-color: white;
    padding: 2rem 3rem;
    border-radius: 1rem;
    box-shadow: 0 0.8rem 2rem rgba(0, 0, 0, 0.08);
    display: flex;
    flex-direction: column;
    align-items: center;
    animation: fadeIn 0.5s ease;
  }
  
  .spinner-wrapper {
    position: relative;
    width: 60px;
    height: 60px;
  }
  
  .spinner-circle {
    position: absolute;
    width: 100%;
    height: 100%;
    border: 4px solid rgba(75, 73, 172, 0.1);
    border-top-color: #4B49AC;
    border-radius: 50%;
    animation: spinner-rotate 1.2s linear infinite;
  }
  
  .spinner-dot {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 15px;
    height: 15px;
    background-color: #4B49AC;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    animation: spinner-pulse 1s ease-in-out infinite alternate;
  }
  
  @keyframes fadeIn {
    0% { opacity: 0; transform: translateY(-20px); }
    100% { opacity: 1; transform: translateY(0); }
  }
  
  @keyframes spinner-rotate {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
  
  @keyframes spinner-pulse {
    0% { transform: translate(-50%, -50%) scale(0.6); opacity: 0.6; }
    100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  }
  
  /* 初始加载动画样式 */
  .initial-loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #ffffff;
    z-index: 10000;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: all 0.3s ease;
  }
</style>
